package com.yty.demo._11_reflection;

import com.yty.demo._4_oop.Kids;
import com.yty.demo._4_oop.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author: yangtaoyao
 * @time: 2020/1/15 9:36
 * @description: 反射
 */
public class ReflectionTest {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Kids kids=new Kids();

        Class c=kids.getClass();

        Class c2=Class.forName("com.yty.demo._4_oop.Person");//
        Person p2= (Person) c2.newInstance();//创建目标类对象
        c.getName();//类的全名（包名+类名）
        c.getSimpleName();//类名
        Class superC=c.getSuperclass();//获取父类
        Class[] superI=c.getInterfaces();//获取所有实现的接口
        ClassLoader classLoader=c.getClassLoader();//类加载器
        Constructor[] constructor=c.getConstructors();//构造器

        //Field getField(String name)
        // 自身及继承的public属性
        Field field1=c.getField("hobby");
        //自身的任何权限的属性
        Field field2=c.getDeclaredField("yearsOld");
        Field[] fields1=c.getFields();
        Field[] fields2=c.getDeclaredFields();

        //Method getMethod(String name, Class<?>... parameterTypes)
        //获取当前类及所有继承的父类的public修饰的方法。仅包括public
        Method method1=c.getMethod("setSex",int.class);
        //获取当前类的所有方法，包括public/private/protected/default修饰的方法。但不包括继承的方法
        Method method2=c.getDeclaredMethod("employee");

        Method[] methods1=c.getMethods();
        Method[] methods2=c.getDeclaredMethods();


        System.out.println(c);
        System.out.println(superC);

        System.out.println("============superI==================");
        for (Class aClass : superI) {
            System.out.println(aClass);
        }

        System.out.println("============constructor==================");
        for (Constructor constructor1 : constructor) {
            System.out.println(constructor1);
        }

        System.out.println("============field==================");
        System.out.println(field1);
        System.out.println(field2);

        System.out.println("============getFields==================");
        for (Field field : fields1) {
            System.out.println("名称："+field.getName());
            System.out.println("修饰符："+field.getModifiers());
            System.out.println("类型："+field.getType());
        }

        System.out.println("============getDeclaredFields==================");
        for (Field field : fields2) {
            System.out.println(field);
        }

        System.out.println("=============method=================");
        System.out.println(method1);
        System.out.println(method2);

        System.out.println("=============getMethods=================");
        for (Method method : methods1) {
            System.out.println("修饰符："+method.getModifiers());
            System.out.println("方法名："+method.getName());
            StringBuilder s1=new StringBuilder();
            for (Class<?> parameterType : method.getParameterTypes()) {
                s1.append(parameterType.getName()+",");
            }
            System.out.println("参数类型："+s1);
            System.out.println("返回值类型："+method.getReturnType().getName());
            System.out.println("-----------------------------------------");
        }

        System.out.println("============getDeclaredMethods==================");
        for (Method method : methods2) {
            System.out.println(method);
        }

        System.out.println("=============getPackage=================");
        System.out.println(c.getPackage().getName());


        Method write=c.getMethod("write");
        //获取私有方法并调用
        Method privateM=c.getDeclaredMethod("privateM");
        Object retObj=write.invoke(kids);
        System.out.println(retObj);
        //先设置可被外部访问
        privateM.setAccessible(true);
        privateM.invoke(kids);

        //修改对象的私有属性
        Field yearsOld=c.getDeclaredField("yearsOld");
        //先设置可被外部访问
        yearsOld.setAccessible(true);
        yearsOld.set(kids,10);
        int age= (int) yearsOld.get(kids);
        System.out.println("yearsOld："+age);

        //动态代理


    }
}
